from cheqed.pyparsing import Literal, Word, ZeroOrMore, Forward, printables, \
     alphas, alphanums

def make_list(s, loc, toks):
    return [ toks ]

def make_parser():
    lpar = Literal("(")
    rpar = Literal(")")
    atom = Word(alphanums + "_-")
    sexp = Forward()
    list_inner = ZeroOrMore(sexp).setParseAction(make_list)
    list = lpar.suppress() + list_inner + rpar.suppress()
    sexp << (atom | list)
    return sexp

parser = make_parser()

def sexp_of_string(string):
    return parser.parseString(string).asList()[0]

def sexp_to_string(sexp):
    if type(sexp) == list:
        if len(sexp) == 0:
            return "()"
        else:
            return "(%s)" % " ".join(map(sexp_to_string, sexp))
    else:
        return sexp

def sexp(obj):
    if type(obj) == str:
        return obj

    if type(obj) == list:
        return map(sexp, obj)

    return obj.sexp()

def unary_op(name, a):
    return map(sexp, [ name, a ])

def binary_op(name, a, b):
    return map(sexp, [ name, a, b ])

def trinary_op(name, a, b, c):
    return map(sexp, [ name, a, b, c ])
